package main

import (
	"fmt"
	"reflect"
)

func declareArray() {
	var a [3]int = [3]int{1, 2, 3}
	fmt.Printf("开始打印数组 %d, 其类型为: %T \n", a, a)
	for i := range a {
		fmt.Println(a[i])
	}

	var b [4]int = [4]int{}
	b[0] = 0
	b[1] = 1
	b[2] = 2
	b[3] = 3
	fmt.Printf("开始打印数组 %d, 其类型为: %T \n", b, b)
	for i := range b {
		fmt.Println(b[i])
	}

	//变长数组
	arrs := [...]int{11, 22, 33, 44}
	fmt.Printf("开始打印数组 %d, 其类型为: %T \n", arrs, arrs)
	for i := range arrs {
		fmt.Println(arrs[i])
	}

	type arr3 [3]int
	c := arr3{1, 2, 3}
	fmt.Printf("开始打印数组 %d, 其类型为: %T \n", c, c)
	for i := range c {
		fmt.Println(c[i])
	}

	var x = [12]int{1, 5: 4, 6, 10: 100, 15}
	fmt.Println(x)
}

func sliceBasic() {
	//切片是左闭右开区间
	var arr [3]int = [3]int{1, 2, 3}
	fmt.Printf("%d的类型是: %T \n", arr[0:2], arr[0:2])
	//构造切片的三种方式
	//1: 对数组进行片段截取 例如: arr[0:2]
	//2: 声明 var slice1 []string; 声明一个空切片
	var slice1 []string
	slice1 = []string{"a", "b"}
	fmt.Printf("%s的类型是: %T \n", slice1, slice1)

	//3: 使用 make 函数 make( []Type, size, cap ) 类型 长度 容量
	slice3 := make([]int, 2)
	slice4 := make([]int, 2, 10)
	fmt.Println(slice3, slice4)
	fmt.Println(len(slice3), len(slice4))
	fmt.Println(cap(slice3), cap(slice4))

	//切片是引用类型，所以你不对它进行赋值的话，它的零值（默认值）是 nil
	var myarr []int
	fmt.Println(myarr == nil)

	//用于各种类型的比较
	reflect.DeepEqual(slice3, slice4)
}

func sliceAppend() {
	myarr := []int{1}
	fmt.Println(myarr)
	//追加一个元素
	myarr = append(myarr, 2)
	fmt.Println(myarr)
	//追加多个元素
	myarr = append(myarr, 3, 4)
	fmt.Println(myarr)
	//追加一个切片, ...表示解包,不能省略
	myarr = append(myarr, []int{7, 8}...)
	fmt.Println(myarr)
	//在第一个位置插入元素
	myarr = append([]int{0}, myarr...)
	fmt.Println(myarr)
	//在中间增加一个切片
	myarr = append(myarr[:5], append([]int{5, 6}, myarr[5:]...)...)
	fmt.Println(myarr)
}

func testSlice() {
	//https://blog.csdn.net/weixin_38125045/article/details/108491746
	//切片是一个引用类型，可以认为它是在原数组上的一个重新定义开始/结束位置的特殊映射。你可以认为它也是一个数组，只是这个数组比较特殊些。
	//切片的长度为连续片段的元素个数，容量却默认是 连续片段开始位置(包含) 到 数组结束位置(包含) 的元素个数。
	//切片的容量可以自定义，如numbers[ start : end : last ]。决定的容量大小：连续片段开始位置start(包含) 到 数组容量结束位置last-start(不包含) 的元素个数。
	//切片可以再进行切片，相当于是 数组根据切片重定义了下标位置（映射切片的下标位置），根据切片的容量重定义了数组最大范围，而后根据该重定义后的数组进行切片。
	//切片引用数组，共用同一个内存空间，更改值会相互影响。

	var numbers4 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	myslice := numbers4[4:6:9]
	fmt.Printf("myslice为 %d, 容量为: %d, 其长度为: %d\n", myslice, cap(myslice), len(myslice))

	//对切片重新进行切片,只能在其容量范围内再次进行切片, 重新切片就相当于在原数组进行切片
	myslice = myslice[:cap(myslice)]
	fmt.Printf("myslice 为: %d, 容量为: %d , 长度为: %d \n", myslice, cap(myslice), len(myslice))
	fmt.Printf("myslice的第四个元素为: %d", myslice[3])
}
func main() {
	declareArray()
	sliceBasic()
	sliceAppend()
	testSlice()
}
